package com.lovegu.server.docking;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.lovegu.server.docking.enums.TestApi;
import com.lovegu.server.docking.service.TestRequest;
import com.lovegu.server.docking.service.TestResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 发送请求器
 *
 * @author 玄鸽
 * @since 2023/8/4
 */
@Slf4j
public class TestConnector {

    private final String successCode = "0000";

    @Value("${url:}")
    private String url;

    @Value("${signMethod:}")
    private String signMethod;

    @Value("${appId:}")
    private String appId;

    @Value("${authCode:}")
    private String authCode;

    @Value("${appSecret:}")
    private String appSecret;

    public <T extends TestResponse> TestOpenResponse<T> executeOpen(TestRequest<T> request) {
        Assert.notNull(request,"请求不能为空！");

        TestApi api = request.api();

        switch (api.getRequest()) {
            case GET:
                return doGet(request);
            case POST:
                return doPost(request);
            default:
                throw new RuntimeException();
        }
    }

    public  <T extends TestResponse> TestOpenResponse<T> doGet(TestRequest<T> request) {
        return null;
    }

    public  <T extends TestResponse> TestOpenResponse<T> doPost(TestRequest<T> request)  {

        Map<String, String> param = new HashMap<>();
        TestApi api = request.api();

        // 拼接请求链接
        String baseUrl = url + "?app_id=" + appId + "&method=" + api.getMethod();

        param.put("app_id", appId);
        param.put("method", request.api().getMethod());
        param.put("sign_method", signMethod);
        param.put("auth_code", authCode);
        param.put("timestamp", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
        param.put("nonce_str", nonceStr());
        param.put("biz_content", JSON.toJSONString(request));
        param.put("sign", generateSignature(param));

        // 构建http请求
        log.info("请求链接: {}", baseUrl);
        log.info("请求参数: {}", param);
        String httpResponse = HttpUtil.post(baseUrl, JSON.toJSONString(param));
        try {
            if (httpResponse.contains(successCode)) {
                log.info("「越洋店铺商家」请求成功, 返回值: {}", JSON.toJSONString(httpResponse));
                return JSON.parseObject(httpResponse,
                        new ParameterizedType() {
                            @Override
                            public Type[] getActualTypeArguments() {
                                return new Type[]{request.loadResponseClz()};
                            }

                            @Override
                            public Type getRawType() {
                                return TestResponse.class;
                            }

                            @Override
                            public Type getOwnerType() {
                                return null;
                            }
                        }
                );
            }else {
                log.error("「越洋店铺商家」请求失败, 返回值: {}", JSON.toJSONString(httpResponse));
            }
        }catch (Exception e) {
            throw new RuntimeException("越洋店铺商家」请求出现错误");
        }
        return null;
    }

    public String nonceStr(){
        String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        int MAX_LENGTH = 32;
        StringBuilder sb = new StringBuilder();
        Random random = new Random();

        for (int i = 0; i < MAX_LENGTH; i++) {
            int randomIndex = random.nextInt(CHARACTERS.length());
            char randomChar = CHARACTERS.charAt(randomIndex);
            sb.append(randomChar);
        }

        return sb.toString();
    }

    public String generateSignature(Map<String, String> data) {
        // 步骤1: 按 ASCII 代码对参数进行排序
        List<Map.Entry<String, String>> sortedParams = new ArrayList<>(data.entrySet());
        sortedParams.sort(Map.Entry.comparingByKey());

        // 步骤2: 构造 stringA
        StringBuilder stringA = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (value != null && !value.isEmpty()) {
                if (stringA.length() > 0) {
                    stringA.append("&");
                }
                stringA.append(key).append("=").append(value);
            }
        }

        // 步骤3: 将 app_secret 附加到 stringA
        String stringSignTemp = stringA + "&app_secret=" + appSecret;

        // 步骤4: 计算 MD5散列并转换为大写
        return calculateMD5(stringSignTemp).toUpperCase();
    }

    private String calculateMD5(String input) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        return sb.toString();
    }
}
